#include "commandlineoptions.h"
#include "stitcher.h"
#include <boost/program_options.hpp>
#include <iostream>
#include <boost/algorithm/string.hpp>

using namespace std;
using namespace cshotel;
using namespace boost;
using namespace boost::program_options;

CommandLineOptions& CommandLineOptions::getInstance() {
    static CommandLineOptions instance;
    return instance;
}

CommandLineOptions::CommandLineOptions() : maximumMatchingVersionImageSize(defaultMaximumMatchingVersionImageSize), outputFormat(PanoramaFile), outputRenderer(Enblend), continueProgram(true), workingDirectory("./"), createThumbnail(false), generateDebugImages(false) {}

void CommandLineOptions::initialize(int argc, char** argv) {
    options_description desc("Allowed options");
    // possible command line options
    desc.add_options()
    ("help", "print help message")
    ("input-file", value< vector<string> >(&inputFileNames), "input files")
    ("output-name", value<string>(&outputName), "Output name, depending on the output format the name of the panorama file (without extension), the SeaDragon directory or a prefix for the transformed files")
    ("output-format", value<string>()->default_value("PanoramaFile"), "Output format. Valid options are SeaDragon, PanoramaFile, TransformedFiles")
    ("output-renderer", value<string>()->default_value("Enblend"), "Output renderer. Valid options are Enblend, OpenCV, VisionWorkbench")
    ("working-directory", value<string>(&workingDirectory)->default_value("tmp"), "Directory for temporary files etc.")
    ("enblend-options", value<string>(&enblendOptions)->default_value("-a -m 500"), "Command line options for enblend")
    ("deepzoom-converter-jar", value<string>(&deepZoomConverterJar)->default_value("DeepZoomConverter.jar"), "Jar file of the Java DeepZoom converter")
    ("deepzoom-converter-options", value<string>(&deepZoomConverterOptions)->default_value("-verbose"), "Command line options for the DeepZoom converter")
    ("java-options", value<string>(&javaOptions)->default_value("-Xmx512m"), "Java command line options")
    ("create-thumbnail", "Create thumbnail")
    ("thumbnail-suffix", value<string>(&thumbnailSuffix)->default_value("_thumb"), "Suffix of the thumbnail file (added between output-name and file extension)")
    ("thumbnail-size", value<int>(&thumbnailSize)->default_value(48), "Size of the thumbnail (which is a square)")
    ("generate-debug-images", "Generate debug images (which are placed in the working directory)")
    ("maximum-matching-version-image-size", value<int>(&maximumMatchingVersionImageSize)->default_value(defaultMaximumMatchingVersionImageSize), "Maximum size of the scaled images that are used for feature extraction")
     ;
    positional_options_description p;
    p.add("input-file", -1);
    
    // parse command line options
    variables_map vm;
    store(command_line_parser(argc, argv).
    options(desc).positional(p).run(), vm);
    notify(vm);
    
    if(vm.count("help")) {
        cout << desc << "\n";
        continueProgram = false;
    }
    
    if(vm.count("create-thumbnail")) {
        createThumbnail = true;
    }
    
    if(vm.count("generate-debug-images")) {
        generateDebugImages = true;
    }
    
    outputFormat = parseOutputFormat(vm["output-format"].as<string>());
    if(outputFormat == UnknownOutputFormat) {
        cout << "Unknown output format" << endl;
        continueProgram = false;
    }
    
    outputRenderer = parseOutputRenderer(vm["output-renderer"].as<string>());
    if(outputRenderer == UnknownOutputRenderer) {
        cout << "Unknown output renderer" << endl;
        continueProgram = false;
    }
    
    if(workingDirectory[workingDirectory.length() - 1] != '/') {
        workingDirectory += "/";
    }
}

CommandLineOptions::OutputFormat CommandLineOptions::parseOutputFormat(string input) {
    to_lower(input);
    if(input == "panoramafile") {
        return PanoramaFile;
    } else if(input == "seadragon") {
        return SeaDragon;
    } else if(input == "transformedfiles") {
        return TransformedFiles;
    } else {
        return UnknownOutputFormat;
    }
}

CommandLineOptions::OutputRenderer CommandLineOptions::parseOutputRenderer(string input) {
    to_lower(input);
    if(input == "enblend") {
        return Enblend;
    } else if(input == "opencv") {
        return OpenCV;
    } else if(input == "visionworkbench") {
        return VisionWorkbench;
    } else {
        return UnknownOutputRenderer;
    }
}

CommandLineOptions::OutputFormat CommandLineOptions::getOutputFormat() {
    return outputFormat;
}

CommandLineOptions::OutputRenderer CommandLineOptions::getOutputRenderer() {
    return outputRenderer;
}

const vector<string>& CommandLineOptions::getInputFileNames() {
    return inputFileNames;
}

int CommandLineOptions::getMaximumMatchingVersionImageSize() {
    return maximumMatchingVersionImageSize;
}

std::string CommandLineOptions::getWorkingDirectory() {
    return workingDirectory;
}

bool CommandLineOptions::getContinueProgram() {
    return continueProgram;
}

string CommandLineOptions::getEnblendOptions() {
    return enblendOptions;
}

string CommandLineOptions::getOutputName() {
    return outputName;
}

string CommandLineOptions::getDeepZoomConverterJar() {
    return deepZoomConverterJar;
}

string CommandLineOptions::getDeepZoomConverterOptions() {
    return deepZoomConverterOptions;
}

string CommandLineOptions::getJavaOptions() {
    return javaOptions;
}

bool CommandLineOptions::getCreateThumbnail() {
    return createThumbnail;
}

string CommandLineOptions::getThumbnailSuffix() {
    return thumbnailSuffix;
}

int CommandLineOptions::getThumbnailSize() {
    return thumbnailSize;
}

bool CommandLineOptions::getGenerateDebugImages() {
    return generateDebugImages;
}


const int CommandLineOptions::defaultMaximumMatchingVersionImageSize;
